package net.dgg.dggcloud.service.jrcrm.service.orf;

import net.dgg.dggcloud.core.json.JsonUtil;
import net.dgg.dggcloud.core.minidao.hibernate.dao.IGenericBaseCommonDao;
import net.dgg.dggcloud.core.util.NJCodeUtil;
import net.dgg.dggcloud.core.util.StringUtils;
import net.dgg.dggcloud.service.common.base.service.BaseService;
import net.dgg.dggcloud.service.common.exception.BizException;
import net.dgg.dggcloud.service.jrcrm.constant.BusinessConstant;
import net.dgg.dggcloud.service.jrcrm.dao.cms.TreeBookDao;
import net.dgg.dggcloud.service.jrcrm.dao.orf.OutlayDao;
import net.dgg.dggcloud.service.jrcrm.dao.orf.OutlayItemDao;
import net.dgg.dggcloud.service.jrcrm.dao.orf.PaymentDao;
import net.dgg.dggcloud.service.jrcrm.dao.orf.PerformanceDao;
import net.dgg.dggcloud.service.jrcrm.entity.orf.Outlay;
import net.dgg.dggcloud.service.jrcrm.entity.orf.OutlayItem;
import net.dgg.dggcloud.service.entity.user.User;
import net.dgg.dggcloud.service.jrcrm.service.cms.BillNumberRuleService;
import net.dgg.dggcloud.service.service.OperationRightService;
import net.dgg.dggcloud.service.service.organization.OrganizationService;
import net.dgg.dggcloud.service.service.user.UserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.math.BigDecimal;
import java.util.*;

/**
 * 财务  费用申请
 *
 * @author 郭伟 2017/11/2
 */
@Service
public class OutlayService extends BaseService {

    @Autowired
    private OutlayDao outlayDao;

    @Autowired
    private PaymentDao paymentDao;

    @Autowired
    private OutlayItemDao outlayItemDao;

    @Resource(name="miniDaoHiberCommonDao")
    protected IGenericBaseCommonDao repository;

    @Autowired
    private PaymentAuditorRecordService paymentAuditorRecordService;

    @Autowired
    private OrganizationService organizationService;
    @Autowired
    private OperationRightService operationRightService;

    @Autowired
    private UserService userService;
    @Autowired
    private BillNumberRuleService billNumberService;

    @Resource
    private NJCodeUtil nJCodeUtil;


    /**
     *  根据ID，查询费用申请相关数据
     * @param id
     * @return
     */
    @Deprecated
    public Outlay getByIdHiber(Long id){
        return this.repository.get(Outlay.class,id);
    }

    /**
     *  根据参数 ，获取费用列表数据数量
     * @param map
     * @return
     */
    public Integer countOutlayByMap(Map map) {
        return outlayDao.countOutlayByMap(map);
    }

    /**
     *  根据参数 ，获取费用列表数据
     * @param map
     * @return
     */
    public List<Map> listOutlayByMap(Map map) {
         return outlayDao.listOutlayByMap(map);
    }

    /**
     * 根据科目获取该科目下需要申请费用的订单信息
     * @param map costId 科目id
     * @return
     */
    public List getOutlayOrder(Map map){

        List<Map> outlayList = paymentDao.getOutlayMessageByMap(map);

        return outlayList;

    }

    public Integer getOutlayOrderCount(Map map){
        return paymentDao.getOutlayMessageCountByMap(map);
    }

    /**
     * 申请费用时，根据订单id，产品id，科目id获取选中的订单信息，包括已申请费用，可申请费用
     * @param map 参数：orderId:订单id </br>
     *             productId:产品id </br>
     *             costId: 科目id </br>
     * @return List<Map>
     */
    public List<Map> getSelectedOrderMessage(Map map){
        return  null;
    }


    public void insertOutLay(String outlayId, Map outlayJson, User u) {
        try {
            Outlay outlay = null;
            String proCostId = "";
            if(StringUtils.isNotBlank(outlayId)){
                outlay = getByIdHiber(Long.parseLong(outlayId));
                if(outlay==null){
                    outlay = new Outlay();
                    outlay.setId(Long.parseLong(outlayId));
                    outlay.setCreateUser(u);
                    outlay.setOutlayNo(billNumberService.updateBillNumberByCode("FY"));
                }else{
                    proCostId = outlay.getCostId();
                }
            }
            outlay.setUpdaterUser(u);
            outlay.setApplyArea(outlayJson.get("applyArea").toString());
            outlay.setCostId(outlayJson.get("costId").toString());
            outlay.setApplyUserId(u.getId());
            outlay.setApplyTime(new Date());
            outlay.setPaymentMethod(outlayJson.get("paymentMethod").toString());
            outlay.setApplySignOrgId(u.getDeptId());
            if(Integer.parseInt(outlayJson.get("type").toString())==1) {
                outlay.setInvoiceCompany(outlayJson.get("invoiceCompany").toString());

            }else{
                outlay.setInvoiceCompany("");
            }
            if(outlayJson.get("paymentMethod").toString().equals("ORF_FYFKFS_1")){
                outlay.setReceiptAccountName("");
                outlay.setReceiptAccount("");
                outlay.setBankName("");
            }else {
                if (StringUtils.isNotBlank(outlayJson.get("receiptAccountName").toString())) {
                    outlay.setReceiptAccountName(outlayJson.get("receiptAccountName").toString());
                }
                if (StringUtils.isNotBlank(outlayJson.get("receiptAccount").toString())) {
                    outlay.setReceiptAccount(outlayJson.get("receiptAccount").toString());
                }
                if (StringUtils.isNotBlank(outlayJson.get("bankName").toString())) {
                    outlay.setBankName(outlayJson.get("bankName").toString());
                }
            }

            outlay.setReceiptCompany(outlayJson.get("receiptCompany").toString());
            outlay.setReceiptContact(outlayJson.get("receiptContact").toString());
            outlay.setContactTelephoneBak(outlayJson.get("contactTelephone").toString());
            outlay.setContactTelephone(nJCodeUtil.encrypt(outlayJson.get("contactTelephone").toString()));
            if(StringUtils.isNotBlank(outlayJson.get("remark").toString())) {
                outlay.setRemark(outlayJson.get("remark").toString());
            }

            //outlay.setAmount(new Double(Double.parseDouble(outlayJson.get("totalAmount").toString())*100).longValue());
            outlay.setAmount((new BigDecimal(outlayJson.get("totalAmount").toString()).multiply(new BigDecimal(100))).longValue());
            outlay.setIsInvoice(Integer.parseInt(outlayJson.get("type").toString()));
            outlay.setStatus(outlayJson.get("status").toString());
            if(outlayJson.get("obj").toString().equals("2")) {
                if (StringUtils.isNotBlank(outlayJson.get("auditUserId").toString())) {
                    outlay.setAuditorUserId(Long.parseLong(outlayJson.get("auditUserId").toString()));
                }
                paymentAuditorRecordService.saveRecord(u, Long.parseLong(outlayId), "",3,1,"ORF_FYZT_1");
            }else{
                outlay.setAuditorUserId(null);
            }

            this.repository.saveOrUpdate(outlay);

            Map mapr = new HashMap();
            if(proCostId.equals(outlay.getCostId())){
                mapr.put("costId",outlay.getCostId());
            }else{
                mapr.put("costId",proCostId);
            }

            List<Map> allPaymentList = null;

            if(StringUtils.isNotBlank(outlayId)){
                allPaymentList = this.getPaymentRecordListByMap(mapr);
                //获取详情，把金额加回去
                List<OutlayItem> outlayItemList = this.getOutlayItemListByOutlayId(Long.parseLong(outlayId));
                for(OutlayItem outlayItem:outlayItemList) {
                    Long totalAmount = outlayItem.getAmount();
                    for (Map map : allPaymentList) {
                        if (outlayItem.getOrderBusinessId().equals(map.get("orderbusinessid"))) {
                            //Long preNotAmount = new Double(Double.parseDouble(map.get("notamount").toString())).longValue();
                           //Long maxAmount = new Double(Double.parseDouble(map.get("amount").toString())).longValue();
                            Long preNotAmount = new BigDecimal(map.get("notamount").toString()).longValue();
                            Long maxAmount = new BigDecimal(map.get("amount").toString()).longValue();
                            //如果当前的可申请的金额大于申请的金额
                            mapr.put("id", map.get("id"));
                            if(preNotAmount + totalAmount>maxAmount){
                                mapr.put("notamount", maxAmount);
                                totalAmount-=maxAmount;
                            }else {
                                mapr.put("notamount", preNotAmount + totalAmount);
                            }
                            this.updatePaymentRecordById(mapr);
                            break;
                        }
                    }
                }
                //删除下面的订单详情
                Map m = new HashMap();
                m.put("id",outlayId);
                this.deleteOutlayItemByMap(m);
            }


            List<Map> itemArray = JsonUtil.json2Obj(outlayJson.get("items").toString(),List.class);
            OutlayItem outlayItem = null;
            Map itemJson = null;
            Long orderBusinessId = null;
            Long orderId = null;
            Long amount = 0l;
            Long notAmount = 0l;
            for(int i=0;i<itemArray.size();i++){
                itemJson = itemArray.get(i);
                outlayItem = new OutlayItem();
                outlayItem.setId(keyWorker.nextId());
                outlayItem.setCreateUser(u);
                outlayItem.setUpdaterUser(u);
                if(itemJson.get("orderId")!=null) {
                    orderId = Long.parseLong(itemJson.get("orderId").toString());
                }
                if(itemJson.get("orderBusinessId")!=null){
                    orderBusinessId = Long.parseLong(itemJson.get("orderBusinessId").toString());
                }
                if(itemJson.get("amount")!=null){
                    //amount = new Double(Double.parseDouble(itemJson.get("amount").toString())*100).longValue();
                    amount = (new BigDecimal(itemJson.get("amount").toString()).multiply(new BigDecimal(100))).longValue();
                }
                if(itemJson.get("notamount")!=null){
                    //notAmount = new Double(Double.parseDouble(itemJson.get("notamount").toString())*100).longValue();
                    notAmount = (new BigDecimal(itemJson.get("notamount").toString()).multiply(new BigDecimal(100))).longValue();
                }

                outlayItem.setOrderId(orderId);
                outlayItem.setAmount(amount);
                outlayItem.setNotAmount(notAmount-amount);
                outlayItem.setCostId(outlay.getCostId());
                outlayItem.setOutlayId(outlay.getId());
                outlayItem.setOrderBusinessId(orderBusinessId);
                this.insertOutlayItem(outlayItem);

                mapr.put("costId",outlay.getCostId());
                allPaymentList = this.getPaymentRecordListByMap(mapr);
                for (Map map : allPaymentList) {
                    if (orderBusinessId.equals(map.get("orderbusinessid"))) {
                        Long preNotAmount = null;
                        if(map.get("notamount")!=null){
                            //preNotAmount = new Double(Double.parseDouble(map.get("notamount").toString())).longValue();
                            preNotAmount = new BigDecimal(map.get("notamount").toString()).longValue();
                        }
                        //如果当前的可申请的金额大于申请的金额
                        mapr.put("id",map.get("id"));
                        if (preNotAmount >= amount) {
                            mapr.put("notamount", preNotAmount - amount);
                            this.updatePaymentRecordById(mapr);
                            break;
                        } else {
                            mapr.put("notamount", 0);
                            amount = amount - preNotAmount;
                            this.updatePaymentRecordById(mapr);
                        }

                    }
                }
            }

        }catch (BizException e)        {
            e.printStackTrace();
            logger.error(e.getMessage());
            throw new BizException(e.getMessage(),10001);
        }
        catch (Exception e)        {
            e.printStackTrace();
            logger.error(e.getMessage());
            throw new RuntimeException(e.getMessage());
        }
    }

    public void insertOutlayItem(OutlayItem outlayItem){
        try {
            this.repository.save(outlayItem);
        }catch (Exception e)        {
            e.printStackTrace();
            logger.error("费用订单详情保存失败");
            throw new RuntimeException("费用订单详情保存失败");
        }
    }


    public List<Map> getAllSelectedOutlayMessageByMap(Map map){
        try {
            return paymentDao.getAllSelectedOutlayMessageByMap(map);
        } catch (Exception e) {
            throw new RuntimeException("fail");
        }
    }

    public void updatePaymentRecordById(Map map){
        try {
            paymentDao.updatePaymentRecordById(map);
        } catch (Exception e) {
            e.printStackTrace();
            logger.error("更新可申请费用失败");
            throw new RuntimeException("fail");
        }
    }

    /**
     * 根据id查询费用申请的详细信息
     * @param map id 费用申请id
     * @return
     */
    public List<Map> getOutlayItemListByMap(Map map){

        List<Map> outlayItemList = outlayItemDao.getOutlayItemListByMap(map);

        return  outlayItemList;
    }

    public List<Map> getPaymentRecordListByMap(Map map){
        List<Map> paymentRecordList = null;
        try {
            paymentRecordList = paymentDao.getPaymentRecordListByMap(map);
        }catch (Exception e) {
            e.printStackTrace();
            logger.error("获取可申请费用列表失败");
            throw new RuntimeException("fail");
        }

        return paymentRecordList;
    }

    /**
     * 根据条件分页查询所有的费用申请
     * @param map
     * @return
     */
    public List<Map> getAllOutlayListByMap(Map map){
        List<Map> outlayList = null;
        try {
            outlayList = outlayDao.getAllOutlayListByMap(map);
        }catch (Exception e) {
            e.printStackTrace();
            throw new RuntimeException("fail");
        }

        return outlayList;
    }

    /**
     * 根据查询条件获取所有费用申请
     * @param map
     * @return
     */
    public Integer countAllOutlayListByMap(Map map){
        Integer count = 0;
        try {
            count = outlayDao.countAllOutlayListByMap(map);
        }catch (Exception e) {
            throw new RuntimeException("fail");
        }

        return count;
    }

    public void updateOutlayStatusByIds(Map map){
        try {
            outlayDao.updateOutlayStatusByIds(map);
        }catch (Exception e) {
            e.printStackTrace();
            logger.error("审核状态更新失败");
            throw new RuntimeException("审核状态更新失败");
        }
    }

    public void deleteOutlayItemByMap(Map map){
        try {
            outlayItemDao.deleteOutlayItemByMap(map);
        }catch (Exception e) {
            e.printStackTrace();
            logger.error("删除费用申请关联的订单失败");
            throw new RuntimeException("删除费用申请关联的订单失败");
        }
    }

    public List<Map> getAuditOutlayListByMap(Map map){
        return outlayDao.getAuditOutlayListByMap(map);
    }

    public Integer countAuditOutlayListByMap(Map map){
        return outlayDao.countAuditOutlayListByMap(map);
    }

    public void deleteOutlayItem(OutlayItem outlayItem){
        this.repository.delete(outlayItem);
    }

    public List<OutlayItem> getOutlayItemListByOutlayId(Long outlayId){
        return repository.findByProperty(OutlayItem.class,"outlayId",outlayId);
    }

    public void updateOutlayAudit(Long outlayId,String nodeName,Long auditUserId,String content){
        Outlay outlay = this.repository.get(Outlay.class,outlayId);
        if (null != outlay){
            outlay.setStatus(nodeName);
            if(nodeName.equals("ORF_FYZT_8") || nodeName.equals("ORF_FYZT_9")){
                outlay.setAuditorUserId(null);
                if(nodeName.equals("ORF_FYZT_8")){
                    outlay.setRejectReason(content);
                    outlay.setRejectTime(new Date());
                }
            }else {
                outlay.setAuditorUserId(auditUserId);
            }
            //完成，更新时间
            if(nodeName.equals("ORF_FYZT_7")){
                outlay.setCarryOutTime(new Date());
                outlay.setStatus("ORF_FYZT_7");
                outlay.setAuditorUserId(null);
            }
        }
        this.repository.saveOrUpdate(outlay);
    }

    /**
     * 用户是否拥有查看部门数据的权限
     * @return
     */
    @Deprecated
    public boolean hasSelectOrgDataRight(User user) {
        return operationRightService.userHasRight(user.getId(), BusinessConstant.BUS_USER_SELECT_ORG_DATA_KEY, "");
    }

    /**
     * 获取用户所在部门及子部门的下用户id集合字符串，以逗号分割
     * @return  id集合字符串
     */
    public String getUserIdsByOrgId(Long orgId) {
        Map omap = new HashMap();
        omap.put("rootOrgId", orgId);
        List<Map> orgList = organizationService.searchOrganization(omap);
        String orgIds = "";
        String userIds = "";
        if (null != orgList && !orgList.isEmpty()) {
            StringBuffer ids = new StringBuffer();
            for (Map map : orgList) {
                ids.append(map.get("id").toString()).append(",");
            }
            if (ids.length() > 0) {
                orgIds = ids.substring(0, ids.lastIndexOf(","));
            }
            if (StringUtils.isNotBlank(orgIds)) {
                Map m = new HashMap();
                m.put("orgId", orgIds);
                List<Map> userList = userService.searchUserList(m);
                if (null != userList && !userList.isEmpty()) {
                    StringBuffer userIdsb = new StringBuffer();
                    for (Map map : userList) {
                        userIdsb.append(map.get("id").toString()).append(",");
                    }
                    if (userIdsb.length() > 0) {
                        userIds = userIdsb.substring(0, userIdsb.lastIndexOf(","));
                    }
                }
            }
        }
        return userIds;
    }






    /**
     * 判断用户是否在部门中
     * @param orgId
     * @param userId
     * @return
     */
    public boolean isUserInOrg(Long orgId,Long userId){
        Map omap = new HashMap();
        omap.put("rootOrgId", orgId);
        List<Map> orgList = organizationService.searchOrganization(omap);
        String orgIds = "";
        if (null != orgList && !orgList.isEmpty()) {
            StringBuffer ids = new StringBuffer();
            for (Map map : orgList) {
                ids.append(map.get("id").toString()).append(",");
            }
            if (ids.length() > 0) {
                orgIds = ids.substring(0, ids.lastIndexOf(","));
            }
            if (StringUtils.isNotBlank(orgIds)) {
                Map m = new HashMap();
                m.put("orgId", orgIds);
                m.put("id",userId);
                List<Map> userList = userService.searchUserList(m);
                if (null != userList && !userList.isEmpty()) {
                    return true;
                }
            }
        }

        return false;
    }

}
